﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class ExpressionTree表达式树_从DataReader获取数据用表达式树填充 : System.Web.UI.Page
{



    protected void Page_Load(object sender, EventArgs e)
    {




        //测试填充实体类值
        var ddd = SetPropertyValue<bookcc, string>(0, new bookcc(), "bookname", "GetString");

        //需要传入GetDecimal
        var dddx = SetValueToEntity<bookcc, decimal>(0, "bookid", "GetDecimal");


        //自动查找获取方法
        Func<bookcc, IDataReader, string> dddv = SetValueToEntity<bookcc, string>(1, "mch");



        //填充数据
        var list = 从DataReader获取数据值<bookcc>();


        //只需要初始化一次即可
        InitDataReaderGetValeMethods();

        从DataReader获取数据值();
    }

    void dxxdd()
    {
        Func<book, IDataReader, string> ddd = (e, r) => (e.bookname = r.GetString(0));
    }

    /// <summary>
    /// 数据功能
    /// </summary>
    Tong.TongUse tong = new Tong.TongUse();

    void 从DataReader获取数据值()
    {
        IDataReader reader = null;
        System.Data.SqlClient.SqlConnection conn = null;
        try
        {
            //查询DataReader
            reader = tong.SqlDataReader("select  * from book", out conn);
            Dictionary<int, DataColumn> columnDics = new Dictionary<int, DataColumn>();

            //生成表头
            for (int i = 0; i < reader.FieldCount; i++)
            {
                columnDics.Add(i, new DataColumn()
                {
                    ColumnName = reader.GetName(i),
                    DataType = reader.GetFieldType(i),
                    Namespace = reader.GetDataTypeName(i)
                });
            }

            //查询读取项
            while (reader.Read())
            {
                foreach (var item in columnDics)
                {
                    //判断字段是否为null
                    if (!reader.IsDBNull(item.Key))
                    {
                        Action<int, IDataRecord> act = null;
                        if (ReaderMethods.TryGetValue(item.Value.DataType, out act))
                        {
                            act(item.Key, reader);
                        }
                    }
                    else
                    {
                        //null处理
                    }
                }
            }


        }
        finally
        {
            if (reader != null)
            {

                reader.Close();
                reader.Dispose();
            }
            if (conn != null)
            {
                conn.Close();
                conn.Dispose();
            }
        }
    }


    public List<T> 从DataReader获取数据值<T>()
        where T : new()
    {
        List<T> result = new List<T>();

        IDataReader reader = null;
        System.Data.SqlClient.SqlConnection conn = null;
        try
        {
            //查询DataReader
            reader = tong.SqlDataReader("select  * from book", out conn);
            Dictionary<int, DataColumn> columnDics = new Dictionary<int, DataColumn>();
            //表达式字典委托 
            Dictionary<int, Action<T, IDataReader>> actionDics = new Dictionary<int, Action<T, IDataReader>>();
            //生成表头
            for (int i = 0; i < reader.FieldCount; i++)
            {
                DataColumn col = new DataColumn()
                {
                    ColumnName = reader.GetName(i),
                    DataType = reader.GetFieldType(i),
                    Namespace = reader.GetDataTypeName(i)
                };
                //添加列
                columnDics.Add(i, col);
                //获取字典值
                actionDics.Add(i, SetValueToEntity<T>(i, col.ColumnName, col.DataType));
            }

            //查询读取项
            while (reader.Read())
            {
                T objT = new T();
                //添加到集合
                result.Add(objT);

                //填充属性值
                foreach (var item in actionDics)
                {
                    //判断字段是否为null
                    if (!reader.IsDBNull(item.Key))
                    {
                        //设置属性值
                        item.Value(objT, reader);
                    }
                    else
                    {
                        //null处理
                    }
                }
            }


        }
        finally
        {
            if (reader != null)
            {

                reader.Close();
                reader.Dispose();
            }
            if (conn != null)
            {
                conn.Close();
                conn.Dispose();
            }
        }

        return result;
    }

    #region 实体类

    /// <summary>
    /// 获取指定索引的数据并且返回调用委托
    /// </summary>
    /// <typeparam name="T">实体类类型</typeparam>
    /// <typeparam name="T1">结果类型</typeparam>
    /// <param name="index">当前对应在DataReader中的索引</param>
    /// <param name="ProPertyName">对应实体类属性名</param>
    /// <param name="FieldType">字段类型</param>
    /// <returns>返回通过调用的委托</returns>
    public Action<T, IDataRecord> SetValueToEntity<T>(int index, string ProPertyName, Type FieldType)
    {
        Type datareader = typeof(IDataRecord);
        var Mdthods = datareader.GetMethods().Where(p => p.ReturnType == FieldType && p.Name.StartsWith("Get") && p.GetParameters().Where(n => n.ParameterType == typeof(int)).Count() == 1);
        //获取调用方法
        System.Reflection.MethodInfo Method = null;
        if (Mdthods.Count() > 0)
        {
            Method = Mdthods.FirstOrDefault();
        }
        else
        {
            throw new EntryPointNotFoundException("没有从DataReader找到合适的取值方法");
        }
        ParameterExpression e = Expression.Parameter(typeof(T), "e");
        ParameterExpression r = Expression.Parameter(datareader, "r");
        //常数表达式
        ConstantExpression i = Expression.Constant(index);
        MemberExpression ep = Expression.PropertyOrField(e, ProPertyName);
        MethodCallExpression call = Expression.Call(r, Method, i);



        //instance.Property = value 这名话是重点
        BinaryExpression assignExpression = Expression.Assign(ep, call);
        var ex = Expression.Lambda(assignExpression, e, r);

        Expression<Action<T, IDataRecord>> resultEx = Expression.Lambda<Action<T, IDataRecord>>(assignExpression, e, r);
        Action<T, IDataRecord> result = resultEx.Compile();

        return result;
    }

    /// <summary>
    /// 获取指定索引的数据并且返回调用委托
    /// </summary>
    /// <typeparam name="T">实体类类型</typeparam>
    /// <typeparam name="T1">结果类型</typeparam>
    /// <param name="index">当前对应在DataReader中的索引</param>
    /// <param name="ProPertyName">对应实体类属性名</param>
    /// <param name="canreturn">是否有返回值</param>
    /// <returns>返回通过调用的委托</returns>
    public Func<T, IDataReader, T1> SetValueToEntity<T, T1>(int index, string ProPertyName)
    {
        Type datareader = typeof(IDataRecord);
        var Mdthods = datareader.GetMethods().Where(p => p.ReturnType == typeof(T1));
        //获取调用方法
        System.Reflection.MethodInfo Method = null;
        if (Mdthods.Count() > 0)
        {
            Method = Mdthods.FirstOrDefault();
        }
        else
        {
            throw new EntryPointNotFoundException("没有从DataReader找到合适的取值方法");
        }
        ParameterExpression e = Expression.Parameter(typeof(T), "e");
        ParameterExpression r = Expression.Parameter(datareader, "r");
        //常数表达式
        ConstantExpression i = Expression.Constant(index);
        MemberExpression ep = Expression.PropertyOrField(e, ProPertyName);
        MethodCallExpression call = Expression.Call(r, Method, i);



        //instance.Property = value 这句话是重点
        BinaryExpression assignExpression = Expression.Assign(ep, call);
        var ex = Expression.Lambda(assignExpression, e, r);

        Expression<Func<T, IDataRecord, T1>> resultEx = Expression.Lambda<Func<T, IDataRecord, T1>>(assignExpression, e, r);
        Func<T, IDataRecord, T1> result = resultEx.Compile();

        return result;
    }

    /// <summary>
    /// 获取设置DataRead与实体类指定列的表达式
    /// </summary>
    /// <typeparam name="T">实体类类型</typeparam>
    /// <typeparam name="T1">结果类型</typeparam>
    /// <param name="index">当前对应在DataReader中的索引</param>
    /// <param name="ProPertyName">对应实体类属性名</param>
    /// <param name="DataReaderGetValueMethodName">调用DataReader中获取值的方法名如:GetString</param>
    /// <returns>返回通过调用的委托</returns>
    public Func<T, IDataReader, T1> SetValueToEntity<T, T1>(int index, string ProPertyName, string DataReaderGetValueMethodName)
    {
        ParameterExpression e = Expression.Parameter(typeof(T), "e");
        ParameterExpression r = Expression.Parameter(typeof(IDataRecord), "r");
        //常数表达式
        ConstantExpression i = Expression.Constant(index);
        MemberExpression ep = Expression.PropertyOrField(e, ProPertyName);
        MethodCallExpression call = Expression.Call(r, typeof(IDataRecord).GetMethod(DataReaderGetValueMethodName, new Type[] { typeof(int) }), i);
        //instance.Property = value 这名话是重点
        BinaryExpression assignExpression = Expression.Assign(ep, call);
        var ex = Expression.Lambda(assignExpression, e, r);

        Expression<Func<T, IDataRecord, T1>> resultEx = Expression.Lambda<Func<T, IDataRecord, T1>>(assignExpression, e, r);
        Func<T, IDataRecord, T1> result = resultEx.Compile();

        return result;
    }

    /// <summary>
    /// 获取设置属性值的委托
    /// </summary>
    /// <typeparam name="T">当关类型名</typeparam>
    /// <typeparam name="T1">返回值</typeparam>
    /// <param name="index">索引</param>
    /// <param name="Entity">实体对像</param>
    /// <param name="ProPertyName">属性名</param>
    /// <param name="DataReaderGetValueMethodName">DataReader获取值方法名 如:"GetString"</param>
    /// <returns></returns>


    public Func<T, IDataRecord, int, T1> SetPropertyValue<T, T1>(int index, T Entity, string ProPertyName, string DataReaderGetValueMethodName)
    {


        //(e, r, index) => (e.bookname = r.GetString(index))
        ParameterExpression e = Expression.Parameter(typeof(T), "e");
        ParameterExpression r = Expression.Parameter(typeof(IDataRecord), "r");
        ParameterExpression i = Expression.Parameter(typeof(int), "index");
        MemberExpression ep = Expression.PropertyOrField(e, ProPertyName);
        MethodCallExpression call = Expression.Call(r, typeof(IDataRecord).GetMethod(DataReaderGetValueMethodName, new Type[] { typeof(int) }), i);

        //instance.Property = value 这名话是重点
        BinaryExpression assignExpression = Expression.Assign(ep, call);

        var ex = Expression.Lambda(assignExpression, e, r, i);

        Expression<Func<T, IDataRecord, int, T1>> resultEx = Expression.Lambda<Func<T, IDataRecord, int, T1>>(assignExpression, e, r, i);

        Func<T, IDataRecord, int, T1> result = resultEx.Compile();


        return result;



    }

    /// <summary>
    /// http://zhidao.baidu.com/link?url=CdGxWD3l5r9H84NPWRSBFtNkea0hn5g0YujI3AIIPUO0W6g4OHxeunQN6qW2Awq2noM2Mfnj1GrD3FOOagamtwIo67ZVK7M6hj_QiwfEJX7
    /// sdd = sdd.Where(s => s.SKUCoding.Split('-').Contains(t));
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="entity"></param>
    /// <param name="propertyname"></param>
    /// <param name="value"></param>
    /// <returns></returns>
    private IEnumerable<T> SearchTcontains<T>(IQueryable<T> entity, string propertyname, string value)// where T : EntityObject
    {
        //   NorthwindEntities en = new NorthwindEntities();
        ParameterExpression pe = Expression.Parameter(typeof(T), "c");
        MemberExpression me = Expression.Property(pe, "CustomerID");
        ConstantExpression ce = Expression.Constant(value);
        Expression right = Expression.Call(
        me,
            //
        typeof(string).GetMethod("Contains", new Type[] { typeof(string) }),
        ce);
        Expression<Func<T, bool>> p = Expression.Lambda<Func<T, bool>>(right, pe);

        //  IEnumerable<T> ems = en.CreateQuery<T>(Plural<T>()).Where(p);
        // return ems as IEnumerable<T>;
        return null;

    }
    #endregion



    #region 处理各种值

    #region 填充DataReader读取方法


    /// <summary>
    /// 单个参数设置处理返回用的方法  集合
    /// </summary>
    private Dictionary<Type, Action<int, IDataRecord>> _ReaderMethods = new Dictionary<Type, Action<int, IDataRecord>>();

    /// <summary>
    /// 单个参数设置处理返回用的方法  集合
    /// </summary>
    public Dictionary<Type, Action<int, IDataRecord>> ReaderMethods
    {
        get { return _ReaderMethods; }
    }
    /// <summary>
    /// 初始化读取DataReader获取各种值的方法
    /// </summary>
    public void InitDataReaderGetValeMethods()
    {
        //所有方法 
        foreach (var method in this.GetType().GetMethods())
        {
            //找到方法对应的属性
            var attrs = method.GetCustomAttributes(typeof(DataReaderTypeAttribute), true);
            if (attrs.Length > 0)
            {
                DataReaderTypeAttribute des = attrs[0] as DataReaderTypeAttribute;
                //从函数签名中创建一个委托,动态返回一个委托
                Action<int, IDataRecord> action = (Action<int, IDataRecord>)Delegate.CreateDelegate(typeof(Action<int, IDataRecord>), this, method);
                //初始化单个参数处理集合
                if (!ReaderMethods.ContainsKey(des.DataFieldType))
                {
                    ReaderMethods.Add(des.DataFieldType, action);
                }
            }
        }
    }

    #endregion




    [DataReaderType(DataFieldType = typeof(bool))]
    public bool GetBoolean(int i, IDataRecord record)
    {

        return record.GetBoolean(i);

    }
    [DataReaderType(DataFieldType = typeof(byte))]
    public byte GetByte(int i, IDataRecord record)
    {

        return record.GetByte(i);

    }
    [DataReaderType(DataFieldType = typeof(char))]
    public char GetChar(int i, IDataRecord record)
    {
        return record.GetChar(i);
    }

    [DataReaderType(DataFieldType = typeof(DateTime))]
    public DateTime GetDateTime(int i, IDataRecord record)
    {
        return record.GetDateTime(i);

    }
    [DataReaderType(DataFieldType = typeof(decimal))]
    public decimal GetDecimal(int i, IDataRecord record)
    {
        return record.GetDecimal(i);

    }

    [DataReaderType(DataFieldType = typeof(double))]
    public double GetDouble(int i, IDataRecord record)
    {
        return record.GetDouble(i);

    }
    [DataReaderType(DataFieldType = typeof(float))]
    public float GetFloat(int i, IDataRecord record)
    {
        return record.GetFloat(i);

    }
    [DataReaderType(DataFieldType = typeof(Guid))]
    public Guid GetGuid(int i, IDataRecord record)
    {
        return record.GetGuid(i);

    }
    [DataReaderType(DataFieldType = typeof(short))]
    public short GetInt16(int i, IDataRecord record)
    {
        return record.GetInt16(i);

    }
    [DataReaderType(DataFieldType = typeof(int))]
    public int GetInt32(int i, IDataRecord record)
    {
        return record.GetInt32(i);
    }
    [DataReaderType(DataFieldType = typeof(long))]
    public long GetInt64(int i, IDataRecord record)
    {

        return record.GetInt64(i);

    }
    [DataReaderType(DataFieldType = typeof(string))]
    public string GetString(int i, IDataRecord record)
    {
        return record.GetString(i);

    }

    #endregion





    /// <summary>
    /// DataReader数据类型特性
    /// </summary>
    public class DataReaderTypeAttribute : Attribute
    {

        /// <summary>
        /// 数据字段类型
        /// </summary>
        public Type DataFieldType { get; set; }
        /// <summary>
        /// 说明
        /// </summary>
        public string Remark { get; set; }
    }

    #region 实体类
    /// <summary>
    /// book:实体类(属性说明自动提取数据库字段的描述信息)
    /// </summary>
    [Serializable]
    protected class bookcc
    {

        #region Model
        private decimal _bookid;
        private string _mch;
        private string _pp;
        private string _qch;
        private string _jj;
        private string _rq;
        private string _jg;
        private string _zl;
        private string _xx;
        private string _isbn1;
        private string _tp;
        private string _nr;
        private string _ml;
        private string _bookname;
        private string _pingpai;
        private string _bookchuban;
        private string _bookdate;
        private string _kaiben;
        private int _yeshu;
        private int _banci;
        private string _zhuang;
        private string _isbn;
        private string _bookcontent;
        private string _bookmulu;
        private decimal _pingji;
        private decimal _shichangjia;
        private decimal _huiyuanjia;
        private decimal _vipjia;
        private int _bestbook;
        private int _tejiabook;
        private int _newsbook;
        private int _kucun;
        private int _chengjiaocount;
        private int _liulancount;
        private int _dazhe;
        private int _nclassid;
        private int _anclassid;
        private string _bookpic;
        private string _bookzz;

        private int _pingjizong;
        private string _shjianame;
        private int _shjiaid;
        /// <summary>
        /// 
        /// </summary>
        public decimal bookid
        {
            set { _bookid = value; }
            get { return _bookid; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string mch
        {
            set { _mch = value; }
            get { return _mch; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string pp
        {
            set { _pp = value; }
            get { return _pp; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string qch
        {
            set { _qch = value; }
            get { return _qch; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string jj
        {
            set { _jj = value; }
            get { return _jj; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string rq
        {
            set { _rq = value; }
            get { return _rq; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string jg
        {
            set { _jg = value; }
            get { return _jg; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string zl
        {
            set { _zl = value; }
            get { return _zl; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string xx
        {
            set { _xx = value; }
            get { return _xx; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string isbn1
        {
            set { _isbn1 = value; }
            get { return _isbn1; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string tp
        {
            set { _tp = value; }
            get { return _tp; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string nr
        {
            set { _nr = value; }
            get { return _nr; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string ml
        {
            set { _ml = value; }
            get { return _ml; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string bookname
        {
            set { _bookname = value; }
            get { return _bookname; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string pingpai
        {
            set { _pingpai = value; }
            get { return _pingpai; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string bookchuban
        {
            set { _bookchuban = value; }
            get { return _bookchuban; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string bookdate
        {
            set { _bookdate = value; }
            get { return _bookdate; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string kaiben
        {
            set { _kaiben = value; }
            get { return _kaiben; }
        }
        /// <summary>
        /// 
        /// </summary>
        public int yeshu
        {
            set { _yeshu = value; }
            get { return _yeshu; }
        }
        /// <summary>
        /// 
        /// </summary>
        public int banci
        {
            set { _banci = value; }
            get { return _banci; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string zhuang
        {
            set { _zhuang = value; }
            get { return _zhuang; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string isbn
        {
            set { _isbn = value; }
            get { return _isbn; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string bookcontent
        {
            set { _bookcontent = value; }
            get { return _bookcontent; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string bookmulu
        {
            set { _bookmulu = value; }
            get { return _bookmulu; }
        }
        /// <summary>
        /// 
        /// </summary>
        public decimal pingji
        {
            set { _pingji = value; }
            get { return _pingji; }
        }
        /// <summary>
        /// 
        /// </summary>
        public decimal shichangjia
        {
            set { _shichangjia = value; }
            get { return _shichangjia; }
        }
        /// <summary>
        /// 
        /// </summary>
        public decimal huiyuanjia
        {
            set { _huiyuanjia = value; }
            get { return _huiyuanjia; }
        }
        /// <summary>
        /// 
        /// </summary>
        public decimal vipjia
        {
            set { _vipjia = value; }
            get { return _vipjia; }
        }
        /// <summary>
        /// 
        /// </summary>
        public int bestbook
        {
            set { _bestbook = value; }
            get { return _bestbook; }
        }
        /// <summary>
        /// 
        /// </summary>
        public int tejiabook
        {
            set { _tejiabook = value; }
            get { return _tejiabook; }
        }
        /// <summary>
        /// 
        /// </summary>
        public int newsbook
        {
            set { _newsbook = value; }
            get { return _newsbook; }
        }
        /// <summary>
        /// 
        /// </summary>
        public int kucun
        {
            set { _kucun = value; }
            get { return _kucun; }
        }
        /// <summary>
        /// 
        /// </summary>
        public int chengjiaocount
        {
            set { _chengjiaocount = value; }
            get { return _chengjiaocount; }
        }
        /// <summary>
        /// 
        /// </summary>
        public int liulancount
        {
            set { _liulancount = value; }
            get { return _liulancount; }
        }
        /// <summary>
        /// 
        /// </summary>
        public int dazhe
        {
            set { _dazhe = value; }
            get { return _dazhe; }
        }
        /// <summary>
        /// 
        /// </summary>
        public int nclassid
        {
            set { _nclassid = value; }
            get { return _nclassid; }
        }
        /// <summary>
        /// 
        /// </summary>
        public int anclassid
        {
            set { _anclassid = value; }
            get { return _anclassid; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string bookpic
        {
            set { _bookpic = value; }
            get { return _bookpic; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string bookzz
        {
            set { _bookzz = value; }
            get { return _bookzz; }
        }
        /// <summary>
        /// 
        /// </summary>
        public DateTime adddate
        {
            get;
            set;
        }
        /// <summary>
        /// 
        /// </summary>
        public int pingjizong
        {
            set { _pingjizong = value; }
            get { return _pingjizong; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string shjianame
        {
            set { _shjianame = value; }
            get { return _shjianame; }
        }
        /// <summary>
        /// 
        /// </summary>
        public int shjiaid
        {
            set { _shjiaid = value; }
            get { return _shjiaid; }
        }
        #endregion Model

    }
    #endregion
}